
(function($){
	$.cacheUtil = {
		objMap:{},
		getCache:function(id){
			if(this.objMap[id]==null){
				this.objMap[id]={};
			}
			return this.objMap[id];
		},
		_getDataKey:function(keys,row){
			var str = "";
			for(var j=0;j<keys.length;j++){
				str+="_"+row[keys[j]];
			}
			if(str.length>0){
				str = str.substring(1);
			}
			return str;
		},
		addData:function(id,keys,rows){//在指定缓冲区中增加数据
			var myCache = this.getCache(id);
			for(var i=0;i<rows.length;i++){
				var row = rows[i];
				var dataKey = this._getDataKey(keys,row);
				if(myCache[dataKey]==null){
					myCache[dataKey] = row;
				}
			}
		},
		removeData:function(id,keys,rows){//在指定缓冲区中删除数据
			var myCache = this.getCache(id);
			for(var i=0;i<rows.length;i++){
				var row = rows[i];
				var dataKey = this._getDataKey(keys,row);
				delete myCache[dataKey];
			}
		},
		getData:function(id){//获取指定缓冲区
			var myCache = this.getCache(id);
			var data = [];
			for(var k in myCache){
				data.push(myCache[k]);
			}
			return data;
		},
		clearData:function(id){//清除指定缓冲区
			delete this.objMap[id];
		},
		check:function(id,keys,rows){//校验指定数组中在返回在缓冲区中的记录
			var myCache = this.getCache(id);
			var data = [];
			for(var i=0;i<rows.length;i++){
				var row = rows[i];
				var dataKey = this._getDataKey(keys,row);

				if(myCache[dataKey]){
					data.push(rows[i]);
				}
			}
			return data;
		}
	};

	$.treeUtil={
		getTreeChildData:function(a,k){
			var r = [];
			for(var i=0;i<a.length;i++){
				if(a[i].id==k){
					if(a[i].children){
						r = a[i].children;
					}
					break;
				}
				if(a[i].children){
					r = this.getTreeChildData(a[i].children,k);
					if(r.length>0){
						break;
					}
				}
			}
			return r;
		},
		addTreeState:function(data){
			if(data.children){
				data.state='closed';
				for(var i=0;i<data.children.length;i++){
					data.children[i] = this.addTreeState(data.children[i]);
				}
			}
			return data;
		}
	};
	$.arrayUtil={
		isEqual:function(v1,v2){
			return v1.sort().toString()==v2.sort().toString();
		},
		notEqual:function(v1,v2){
			return !this.isEqual(v1,v2);
		}
	};
	$.inputUtil={
		defaultWidth:0,
		getDefaultWidth:function(){
			if(this.defaultWidth==0){
				//设置组件默认宽度
				var c = $("<input type='text'>").css('visibility','hidden').appendTo('body');
				this.defaultWidth = c.outerWidth();
				c.remove();
			}
			return this.defaultWidth;
		}
	};
	$.jsonUtil={
		clone:function (obj){
			if (obj === null) return null;
			var o = $.isArray(obj) ? [] : {};
			for(var i in obj){
				o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? arguments.callee(obj[i]) : obj[i]);
			}
			return o;
		},
		json2xml:function(o, tab){
			var xml="";
			var toXml = function(v, name, ind) {
				var xml = "";
				if (v instanceof Array) {
					for (var i=0, n=v.length; i<n; i++){
						xml += ind + toXml(v[i], name, ind+"\t") + "\n";
					}
				}else if (typeof(v) == "object") {
					var hasChild = false;
					xml += ind + "<" + name;
					for (var m in v) {
						if (m.charAt(0) == "@") {
							xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
						}else{ 
							hasChild = true;
						}
					}
					 xml += hasChild ? ">" : "/>";
					 if (hasChild) {
						for (var m in v) {
							if (m == "#text"){
								xml += v[m];
							}else if (m == "#cdata"){
								xml += "<![CDATA[" + v[m] + "]]>";
							}else if (m.charAt(0) != "@"){
								xml += toXml(v[m], m, ind+"\t");
							}
						}
						xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">";
					}
				}else {
					//if(v)  //去除值为空串等情况不能正确转换
					xml += ind + "<" + name + ">" + v.toString() +  "</" + name + ">";
				}
				return xml;
			};

			for (var m in o){
				xml += toXml(o[m], m, "");
			}
			
			return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
		},
		xml2jsonObj: function(xml,extended){
			if(!xml) return {};

			function parseXML(node, simple){
				if(!node) return null;
				var txt = '', obj = null, att = null;
				var nt = node.nodeType, nn = jsVar(node.localName || node.nodeName);
				var nv = node.text || node.nodeValue || '';
				if(node.childNodes){
					if(node.childNodes.length>0){
						$.each(node.childNodes, function(n,cn){
							var cnt = cn.nodeType, cnn = jsVar(cn.localName || cn.nodeName);
							var cnv = cn.text || cn.nodeValue || '';
							if(cnt == 8){
								return;
							}else if(cnt == 3 || cnt == 4 || !cnn){
								if(cnv.match(/^\s+$/)){
									return;
								};
								txt += cnv.replace(/^\s+/,'').replace(/\s+$/,'');
							}else{
								obj = obj || {};
								if(obj[cnn]){
									if(!obj[cnn].length) obj[cnn] = myArr(obj[cnn]);
									obj[cnn] = myArr(obj[cnn]);
									obj[cnn][ obj[cnn].length ] = parseXML(cn, true);

									obj[cnn].length = obj[cnn].length;
								}else{
									obj[cnn] = parseXML(cn);
								}
							}
						});
					}
				}

				if(node.attributes){
					if(node.attributes.length>0){
						att = {}; obj = obj || {};
						$.each(node.attributes, function(a,at){
							var atn = jsVar(at.name), atv = at.value;
							att[atn] = atv;
							if(obj[atn]){
								obj[cnn] = myArr(obj[cnn]);
								obj[atn][ obj[atn].length ] = atv;
								obj[atn].length = obj[atn].length;
							}else{
								obj[atn] = atv;
							}
						});
					}
				}

				if(obj){
					//obj = $.extend( (txt!='' ? new String(txt) : {}),obj || {});
					//txt = (obj.text) ? (typeof(obj.text)=='object' ? obj.text : [obj.text || '']).concat([txt]) : txt;
					if(txt) obj._text = txt;
					txt = '';
				}

				var out = obj || txt;
				if(extended){
					if(txt) out = {};//new String(out);
					txt = out.text || txt || '';
					if(txt) out.text = txt;
					if(!simple) out = myArr(out);
				}
				return out;
			}

			function jsVar(s){ 
				return String(s || '').replace(/-/g,"_"); 
			}

			function isNum(s){
				var regexp=/^((-)?([0-9]+)(([\.\,]{0,1})([0-9]+))?$)/
				return (typeof s == "number") || regexp.test(String((s && typeof s == "string") ? jQuery.trim(s) : ''));
			}

			function myArr(o){
				if(!$.isArray(o)) o = [ o ]; o.length=o.length;
				return o;
			};

			if(typeof xml=='string') xml = this.text2xml(xml);
			if(!xml.nodeType) return;
			if(xml.nodeType == 3 || xml.nodeType == 4) return xml.nodeValue;
			var root = (xml.nodeType == 9) ? xml.documentElement : xml;
			var out = parseXML(root, true);
			xml = null; root = null;
			return out;
		},
		xml2json:function(xml,tab) {
			var X = {
				toObj: function(xml) {
					var o = {};
					if (xml.nodeType==1) {   // element node ..
						if (xml.attributes.length){   // element with attributes  ..
							for (var i=0; i<xml.attributes.length; i++){
								o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
							}
						}
						if (xml.firstChild) { // element has child nodes ..
							var textChild=0, cdataChild=0, hasElementChild=false;
							for (var n=xml.firstChild; n; n=n.nextSibling) {
								if (n.nodeType==1) {
									hasElementChild = true;
								}else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)){
									textChild++; // non-whitespace text
								}else if (n.nodeType==4){
									cdataChild++; // cdata section node
								}
							}
							if (hasElementChild) {
								if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
									X.removeWhite(xml);
									for (var n=xml.firstChild; n; n=n.nextSibling) {
										if (n.nodeType == 3){  // text node
											o["#text"] = X.escape(n.nodeValue);
										}else if (n.nodeType == 4) { // cdata node
											o["#cdata"] = X.escape(n.nodeValue);
										}else if (o[n.nodeName]) {  // multiple occurence of element ..
											if (o[n.nodeName] instanceof Array){
												o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
											}else{
												o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
											}
										}else { // first occurence of element..
											o[n.nodeName] = X.toObj(n);
										}
									}
								}else{ // mixed content
									if (!xml.attributes.length){
										o = X.escape(X.innerXml(xml));
									}else{
										o["#text"] = X.escape(X.innerXml(xml));
									}
								}
							}else if (textChild) { // pure text
								if (!xml.attributes.length){
									o = X.escape(X.innerXml(xml));
								}else{
									o["#text"] = X.escape(X.innerXml(xml));
								}
							}else if (cdataChild) { // cdata
								if (cdataChild > 1){
									o = X.escape(X.innerXml(xml));
								}else{
									for (var n=xml.firstChild; n; n=n.nextSibling){
										o["#cdata"] = X.escape(n.nodeValue);
									}
								}
							}
						}
						if (!xml.attributes.length && !xml.firstChild) o = null;
					}else if (xml.nodeType==9) { // document.node
						o = X.toObj(xml.documentElement);
					}else{
						alert("unhandled node type: " + xml.nodeType);
					}
					return o;
				},
				toJson: function(o, name, ind) {
					var json = name ? ("\""+name+"\"") : "";
					if (o instanceof Array) {
						for (var i=0,n=o.length; i<n; i++){
							o[i] = X.toJson(o[i], "", ind+"\t");
						}
						json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
					}else if (o == null){
						json += (name&&":") + "\"\"";
					}else if (typeof(o) == "object") {
						var arr = [];
						for (var m in o){
							arr[arr.length] = X.toJson(o[m], m, ind+"\t");
						}
						json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
					}else if (typeof(o) == "string"){
						json += (name&&":") + "\"" + o.toString() + "\"";
					}else{
						json += (name&&":") + o.toString();
					}
					return json;
				},
				innerXml: function(node){
					var s = ""
					if ("innerHTML" in node){
						s = node.innerHTML;
					}else {
						var asXml = function(n) {
							var s = "";
							if (n.nodeType == 1) {
								s += "<" + n.nodeName;
								for (var i=0; i<n.attributes.length;i++){
									s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
								}
								if (n.firstChild) {
									s += ">";
									for (var c=n.firstChild; c; c=c.nextSibling){
										s += asXml(c);
									}
									s += "</"+n.nodeName+">";
								}else{
									s += "/>";
								}
							}else if (n.nodeType == 3){
								s += n.nodeValue;
							}else if (n.nodeType == 4){
								s += "<![CDATA[" + n.nodeValue + "]]>";
							}
							return s;
						};
						for (var c=node.firstChild; c; c=c.nextSibling){
							s += asXml(c);
						}
					}
					return s;
				},
				escape: function(txt) {
					return txt.replace(/[\\]/g, "\\\\").replace(/[\"]/g, '\\"').replace(/[\n]/g, '\\n').replace(/[\r]/g, '\\r');
				},
				removeWhite: function(e) {
					e.normalize();
					for (var n = e.firstChild; n; ) {
						if (n.nodeType == 3) {  // text node
							if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
								var nxt = n.nextSibling;
								e.removeChild(n);
								n = nxt;
							}else{
								n = n.nextSibling;
							}
						}else if (n.nodeType == 1) {// element node
							X.removeWhite(n);
							n = n.nextSibling;
						}else {// any other node
							n = n.nextSibling;
						}
					}
					return e;
				}
			};
			if (xml.nodeType == 9) {// document node
				xml = xml.documentElement;
			}
			var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
			if(tab){
				return "{\n" + tab + (tab ? json.replace(/\t/g, tab): json.replace(/\t|\n/g, "")) + "\n}";
			}else{
				return "{\n" + json.replace(/\t|\n/g, "") + "\n}";
			}			
		},
		text2xml: function(str) {
			var out;
			try{
				var xml = ((!$.support.opacity && !$.support.style))?new ActiveXObject("Microsoft.XMLDOM"):new DOMParser();
				xml.async = false;
			}catch(e){ throw new Error("XML Parser could not be instantiated") };
			try{
				if((!$.support.opacity && !$.support.style)) out = (xml.loadXML(str))?xml:false;
				else out = xml.parseFromString(str, "text/xml");
				oErr = xml.parseError;
				if (oErr.errorCode != 0) {
					alert("解析XML数据错误：\n" + oErr.reason + "\nLine:" + oErr.line + "\nLinepos:" + oErr.linepos + "\nsrcText:\n" + oErr.srcText);
				}
			}catch(e){
				throw new Error("Error parsing XML string") 
			};
			return out;
		},
		json2str:function(O){ 
			var S = []; 
			var J = ""; 
			var objType = Object.prototype.toString.apply(O); 
			if ( objType === '[object Array]') { 
				for (var i = 0; i < O.length; i++){ 
					S.push(this.json2str(O[i])); 
				} 
				J = '[' + S.join(',') + ']'; 
			} else if (objType === '[object Date]') { 
				J = "new Date(" + O.getTime() + ")"; 
			} else if (objType === '[object RegExp]' || objType === '[object Function]') { 
				J = O.toString(); 
			} else if (objType === '[object Object]') { 
				for (var i in O) {
					var d = O[i];
					if(typeof(O[i]) == 'string'){ 
						d = '"' + O[i] + '"'; 
					}else if(typeof(O[i]) === 'object'){ 
						d = this.json2str(O[i]); 
					} 
					S.push('"' + i + '":' + d); 
				} 
				J = '{' + S.join(',') + '}'; 
			}
			return J;
		}
	};
})(jQuery);
